// Author: Bjorn Schobben

#include "Land.h"

Land::Land(const std::string& newName) : name(newName)
{
}

Land::Land(const Land& rhs): name(rhs.name)
{
	Copy(rhs);
}

Land::~Land()
{
	Clear();
}

// Copy a land
void Land::Copy(const Land& rhs)
{
	std::list<Province*>::const_iterator provinceIt;

	for(provinceIt = rhs.provinces.begin(); provinceIt != rhs.provinces.end(); ++provinceIt)
	{
		const Province* province = *provinceIt;

		InsertNewProvince(*province);
	}
}

// Clear land contents, clean up
void Land::Clear()
{
	std::list<Province*>::iterator it;
	for(it = provinces.begin(); it != provinces.end(); ++it)
	{
		delete *it;
	}

	provinces.clear();
}

void Land::SetName(const std::string& newName)
{
	name = newName;
}


const std::string& Land::GetName() const
{
	return name;
}

// Get provinces list
std::list<Province*>& Land::GetProvinces()
{
	return provinces;
}

Province* Land::InsertNewProvince(const std::string& name)
{
	// Insert empty province
	return InsertProvince(new Province(name));
}

Province* Land::InsertNewProvince(const Province& province)
{
	return InsertProvince(new Province(province));
}

Province* Land::InsertProvince(Province* province)
{
	provinces.push_back(province);

	return provinces.back();
}

// Return if this land is colored according to the 4-color problem
bool Land::IsCompleted() const
{
	std::list<Province*>::const_iterator it;
	bool result = true;
	
	// Ask each province if it is colored, and if its neighbour does not already contain the same color
	for(it = provinces.begin(); it != provinces.end(); ++it)
	{
		const Province* province = *it;

		Color provinceColor = province->GetColor();

		if (!provinceColor.IsColor() || province->NeighbourContainsColor(provinceColor))
		{
			result = false;
			break;
		}
	}

	return result;
}

// Set a province's color
bool Land::SetColor(const std::string& provinceName, Color color)
{
	Province *province = GetProvince(provinceName);
	bool result = false;
	

	if (province)
	{
		// Set the province's color
		province->SetColor(color);

		result = true;
	}

	return result;
}

// Get a pointer to a province
Province* Land::GetProvince(const std::string& provinceName)
{
	std::list<Province*>::iterator it;
	Province *result = 0;
	

	for(it = provinces.begin(); it != provinces.end(); ++it)
	{
		Province* province = *it;

		// If names match
		if (province->GetName() == provinceName)
		{
			// Then return the pointer
			result = province;
			break;
		}
	}

	return result;
}

// Same as above, but constant pointer now
const Province* Land::GetProvince(const std::string& provinceName) const
{
	std::list<Province*>::const_iterator it;
	const Province *result = 0;
	

	for(it = provinces.begin(); it != provinces.end(); ++it)
	{
		const Province* province = *it;

		if (province->GetName() == provinceName)
		{
			result = province;
			break;
		}
	}

	return result;
}

// Accumulate unique colors in this land to the colorTable
void Land::GetUniqueColors(std::list<Color>& colorTable) const
{
	std::list<Province*>::const_iterator it;
	std::list<Color>::iterator colorIt;

	for(it = provinces.begin(); it != provinces.end(); ++it)
	{
		const Province* province = *it;

		// Accumulate province's color
		province->GetUniqueColors(colorTable);
	}
}

// Clear neighbours of all provinces
void Land::ClearNeighbours()
{
	std::list<Province*>::iterator it;

	for(it = provinces.begin(); it != provinces.end(); ++it)
	{
		Province* province = *it;

		// Clear neighbours
		province->ClearNeighbours();
	}
}


// Update neighbours list
void Land::UpdateNeighbours(const Land* neighbourLand)
{
	std::list<Province*>::iterator it;
	std::list<Province*>::const_iterator neighbourIt;

	
	for(it = provinces.begin(); it != provinces.end(); ++it)
	{
		Province* province = *it;

		// Default is to update with own neighbours
		const std::list<Province*> *neighbourProvinces = &provinces;

		// But we can test for neighbours of an other land aswell
		if (neighbourLand)
			neighbourProvinces = &(neighbourLand->provinces);

		for(neighbourIt = neighbourProvinces->begin(); neighbourIt != neighbourProvinces->end(); ++neighbourIt)
		{
			Province* neighbour = *neighbourIt;

			// If this province is the province we are inspecting, skip it
			if (province == neighbour)
				continue;

			// If this province is neighbouring a province
			if (province->IsNeighbouring(*neighbour))
			{
				// Insert neighbour
				province->InsertNeighbour(*neighbour);
			}
		}
	}
}




